// ## 2023/05/03 # 江东新风 # 函数主体改写 ##
// ## 2022/11/01 # 铃 # 在新的自动化内政中,生产也成为自动化,为新的内政系统设定参数和算法 ##
// ## 2022/08/14 # 铃 # 在新的人口系统中,生产的逻辑也发生了很大变化,重做相关函数。 ##
// ## 2021/10/11 # 江东新风 # 造船和工坊对应特技错误 ##
// ## 2021/10/01 # 江东新风 # namespace的韩文改成英文 ##
// ## 2021/09/15 # 江东新风 # 更改pk::core[]函数为英文##
// ## 2020/10/23 #江东新风#同步马术书大神的更新，添加城市数量惩罚，修复战役模式情况的nullptr错误##
// ## 2020/08/24 # 氕氘氚 # 常量修改 ##
// ## 2020/08/16 #江东新风#has_skill函数替換##
/*
@수정자 : 기마책사
@Update: '20.8.29  // 수정내용: 유저_도시수_패널티 추가, 캠페인에서는 커스텀 세팅 사용 불가하도록 수정
*/

namespace PRODUCE_TIME_COST
{
	const bool 玩家_城市数_惩罚 = false; // 유저세력에 대해서 도시수에 비례하여 생산량 디버프 (도시당 1% 감소)
	//---------------------------------------------------------------------------

	class Main
	{
		Main()
		{
			pk::set_func(103, pk::func103_t(callback));
		}

		int callback(const pk::detail::arrayptr<pk::person @> &in actors, int weapon_id)
		{
			pk::list<pk::person @> actor_list;
			for (int i = 0; i < actors.length; i++)
			{
				actor_list.add(actors[i]);
			}
			return get_produce_time(actor_list, weapon_id);
		}

	} Main main;

	int get_produce_time(pk::list<pk::person @> actors, int weapon_id)
	{

		if (!pk::is_valid_equipment_id(weapon_id))
			return 0;
		if (weapon_id < 兵器_冲车)
			return 0;
		if (!pk::is_alive(actors[0]))
			return 0;

		int n = 0, sum = 0, max = 0, skill_id = -1;
		bool has_skill = false;
#if param_set
		if (weapon_id == 兵器_冲车 or weapon_id == 兵器_井阑 or weapon_id == 兵器_投石 or weapon_id == 兵器_木兽)
			skill_id = pk::get_produce_param().workshop_skill; // int(pk::core["weapon_produce.workshop_skill"]);
		else if (weapon_id == 兵器_楼船 or weapon_id == 兵器_斗舰)
			skill_id = pk::get_produce_param().shipyard_skill; // int(pk::core["weapon_produce.shipyard_skill"]);

#endif
#if not_param_set
		if (weapon_id == 兵器_冲车 or weapon_id == 兵器_井阑 or weapon_id == 兵器_投石 or weapon_id == 兵器_木兽)
			skill_id = int(pk::core["weapon_produce.workshop_skill"]);
		else if (weapon_id == 兵器_楼船 or weapon_id == 兵器_斗舰)
			skill_id = int(pk::core["weapon_produce.shipyard_skill"]);
#endif

		for (int i = 0; i < actors.count; i++)
		{
			pk::person @actor = actors[i];
			if (pk::is_alive(actor))
			{
#if param_set
				int s = actor.stat[pk::get_produce_param().stat];
#endif
#if not_param_set
				int s = actor.stat[int(pk::core["weapon_produce.stat"])];
#endif
				sum = sum + s;
				max = pk::max(max, s);
				if (ch::has_skill(actor, skill_id))
					has_skill = true;
			}
		}

		int top = 生产时长上限;
		pk::city @city;

		pk::building @building = pk::get_building(actors[0].service);
		if (weapon_id >= 兵器_走舸)
		{
			if (pk::is_alive(building))
			{
				@city = pk::building_to_city(building);
				if (pk::has_facility(city, 设施_练兵所))
				{
					top = pk::max(生产时长上限 - 2, 3);
				}
			}
		}

		if (n < 2)
			n = 2;

		float exp_eff = 1.0f;
		float absent_eff = 1.0f;
		float expend_eff = 1.0f;

		float facility_eff = 1.0f;
		if (pk::is_alive(building))
			facility_eff = pk::is_valid_city_id(building.get_id()) ? func_5c7040(pk::building_to_city(building), weapon_id) : 1.0f;

		bool is_auto_affairs = auto_inner::is_auto_affairs(building, actors);
		if (is_auto_affairs) // 只有在人数为1，开启自动内政，且有执政官经验时享受加成
		{
			// exp_eff = main.get_exp_eff(actors[0].get_id(), weapon_id);
			int rank_type = weapon_id >= 兵器_走舸 ? 内政自动化_造船 : 内政自动化_攻具;
			exp_eff = auto_inner::get_exp_eff(actors[0].get_id(), rank_type);
			absent_eff = auto_inner::get_absent_eff(actors[0], rank_type);

			int service_id = actors[0].service;
			if (pk::is_valid_base_id(service_id))
			{
				auto building_p = ch::get_baseIA(service_id);
				int effic = 0;
				if (weapon_id < 兵器_走舸)
					effic = building_p.punch_effic;
				else
					effic = building_p.boat_effic;
				// 由于自动内政为持续消耗,因此计算方式上需要增加产量平衡
				expend_eff = float(effic) / pk::get_equipment(weapon_id).gold_cost * 5 * 1.35 * (city !is null and pk::has_facility(city, 设施_练兵所) ? 1.15 : 1); // 多项式拟合结果

				// pk::trace(pk::format("兵器为:{}, expend_eff{}，gold_cost:{}", weapon_id, expend_eff, pk::get_equipment(weapon_id).gold_cost));
			}
		}

		bool is_city_buff = weapon_id >= 兵器_走舸 and city_tech::is_building_force_has_city(building, 30);

		// 自动内政按照天数计算不妥:1.天数<4的时候,不同武将,不同开支可能结果都一样,玩家反馈有困惑,2.没有必要倒算一次再倒算回来.
		// 而且自动内政只有一个武将,sum + max - 200被限制了最小值24导致谁来都一样
		// 如果按照9999天,会一直有个0.1%的产量,玩家会经常来询问.
		// 自动内政直接按照开支计算就好,只要公式一样,调用参数一样就行.
		if (is_auto_affairs)
		{
			int m = 0;

			m = int(expend_eff * exp_eff * facility_eff * absent_eff * 100);

			m = int(m * (1 + (sum - 70.0) / 100.0));

			// 难度修正
			m = int(m * (building.is_player() ? 100 : inter::domestic_difficulty_impact()) / 100.f);

			// 玩家电脑区别对待
			m = int(m * (building.is_player() ? 玩家生产倍率 : 电脑生产倍率) / 100);
			m = m * 100 / 生产时长倍率;

			// 特技影响
			if (has_skill)
				m = m * 150 / 100; // 手动内政只影响时间不影响开支,自动内政会同时影响花费,因此2倍的参数不适合自动内政算法,暂时给1.5倍,等以后有没有更好的处理办法

			if (is_city_buff)
				m = int(m * 1.3);

			if (pk::enemies_around(building))
				m = m * 兵临城下时生产倍率 / 100;
			return m;
		}

		n = top - pk::max(int((pk::min(sum + max, 300)) - 200), 24) / 24;

		n = n * 生产时长倍率 / 100;

		// 관련 특기를 가지고 있다면 반감
		if (has_skill)
			n = n * pk::core::skill_constant_value(skill_id) / 100; // 直接会根据兵器id选择对应特技了

		if (is_city_buff)
			n = int(n * 0.7);

		if (pk::enemies_around(building))
			n = n / 兵临城下时生产倍率 * 100;

		// 难度修正
		n = int(n * 100.0 / (building.is_player() ? 100 : inter::domestic_difficulty_impact()));

		// 玩家电脑区别对待
		n = int(n * 100.0 / (building.is_player() ? 玩家生产倍率 : 电脑生产倍率));

		n = pk::max(n, 1); // overflow 방지용 ('18.11.17)
		return n;
	}

	// 参照兵器生产的相关函数改的
	float func_5c7040(pk::city @city, int weapon_id)
	{
		int level1 = 0, level2 = 0;
		if (weapon_id == 兵器_冲车 or weapon_id == 兵器_木兽 or weapon_id == 兵器_井阑 or weapon_id == 兵器_投石)
		{
			for (int i = 0; i < city.max_devs; i++)
			{
				pk::building @building = city.dev[i].building;
				if (pk::is_alive(building))
				{
					if (building.facility == 设施_工房)
						building.completed ? level1++ : 0;
				}
			}
			if (level1 > 0)
				return 1.0f;
		}
		else if (weapon_id == 兵器_楼船 or weapon_id == 兵器_斗舰)
		{
			for (int i = 0; i < city.max_devs; i++)
			{
				pk::building @building = city.dev[i].building;
				if (pk::is_alive(building))
				{
					if (building.facility == 设施_造船)
						building.completed ? level1++ : 0;
				}
			}
			if (level1 > 0)
				return 1.0f;
		}
		return 0.3f;
	}
}